﻿/*
 *author:keily ,department 2,wuda geo
 *create date:2013-1-25
 *description:集合基础功能，table 2 entity，entity 2 table转换类
 */


using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace GeoWeb.Common
{
    /// <summary>
    /// 集合基础功能，table 2 entity，entity 2 table转换类
    /// </summary>
    public class IListHelper
    {
        /// <summary>
        /// 合并2个datatable并返回一个新的合并后的table
        /// </summary>
        /// <param name="mainTable"></param>
        /// <param name="mergeTable"></param>
        /// <returns></returns>
        public static DataTable MergeDataTable(DataTable mainTable, DataTable mergeTable)
        {
            mainTable.Merge(mergeTable);
            return mainTable;
        }
        /// <summary>
        /// 将dataset输入为xml文件
        /// </summary>
        /// <param name="dataset">dataset数据集</param>
        /// <param name="filename">输出文件路（包含文件名）</param>
        /// <returns></returns>
        public static bool DataSetToXml(DataSet dataset, string filename)
        {
            bool result;
            try
            {
                dataset.WriteXml(filename);
                result = true;
            }
            catch (Exception ex)
            {
                IListHelper._exceptionMessage = ex.Message;
                result = false;
            }
            return result;
        }
        /// <summary>
        /// 查询datatable，获取满足条件的行集合
        /// </summary>
        /// <param name="table">datatable</param>
        /// <param name="expression">查询条件,类似sql语句条件表达式 ,如string expression = "Date > #1/1/00#";</param>
        /// <returns></returns>
        public static DataRow[] SelectRows(DataTable table, string expression)
        {
            DataRow[] result;
            try
            {
                result = table.Select(expression);
            }
            catch (Exception ex)
            {
                IListHelper._exceptionMessage = ex.Message;
                result = null;
            }
            return result;
        }
        /// <summary>
        /// 将类类型的实体转换为datatable
        /// </summary>
        /// <param name="entitys">实体</param>
        /// <returns>返回datatable</returns>
        public static DataTable Enitiy2DataTable<T>(List<T> entitys) where T : class
        {
            //如果实体为null，抛出异常
            if (entitys == null || entitys.Count < 1)
            {
                throw new Exception("需转换的集合为空");
            }

            DataTable dataTable = new DataTable();

            //反射获取实体类型
            T t = entitys[0];
            Type type = t.GetType();
            PropertyInfo[] properties = type.GetProperties();
            PropertyInfo[] array = properties;
            for (int i = 0; i < array.Length; i++)
            {
                PropertyInfo propertyInfo = array[i];
                dataTable.Columns.Add(propertyInfo.Name, propertyInfo.PropertyType);
            }
            //遍历实体，赋值
            foreach (object obj in entitys)
            {
                if (obj.GetType() != type)
                {
                    throw new Exception("要转换的集合元素类型不一致");
                }
                object[] array2 = new object[properties.Length];
                for (int j = 0; j < properties.Length; j++)
                {
                    array2[j] = properties[j].GetValue(obj, null);
                }
                dataTable.Rows.Add(array2);
            }
            return dataTable;
        }
        /// <summary>
        /// 将datatable类型转换为类类型的实体集合
        /// </summary>
        /// <param name="dt">需要转换的datatable</param>
        /// <returns></returns>
        public static IList<T> Dt2List<T>(DataTable dt) where T : class
        {
            //声明并定义返回的类对象集合
            List<T> list = new List<T>();
            //遍历datatable数据集合
            foreach (DataRow dataRow in dt.Rows)
            {
                //反射生成泛型对象类的实体，并初始化
                T t = (default(T) == null) ? Activator.CreateInstance<T>() : default(T);
                //获取生成的对象的属性信息
                PropertyInfo[] properties = t.GetType().GetProperties();
                PropertyInfo[] array = properties;
                //遍历属性，将相应的table值赋值给实体
                for (int i = 0; i < array.Length; i++)
                {
                    PropertyInfo propertyInfo = array[i];
                    string name = propertyInfo.Name;
                    if (dt.Columns.Contains(name) && propertyInfo.CanWrite)
                    {
                        object obj = dataRow[name];
                        //如果table中此列的值为null，则将此属性set为null
                        //注意，如果 是一些引用类型，不能将引用值设置为null，就会抛出异常
                        //如 datetime类型，所以建议class中 datetime应该表示为 datetime？或者 Nullable<dateitme>

                        if (obj != DBNull.Value)
                        {
                            propertyInfo.SetValue(t, obj, null);
                        }
                    }
                }
                list.Add(t);
            }
            return list;
        }
        /// <summary>
        /// 将枚举转换为table，实际中可能用的比较少
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <param name="key">新datatable的key列名称</param>
        /// <param name="val">新datatable的value列名称</param>
        /// <returns></returns>
        public static DataTable EnumToDataTable(Type enumType, string key, string val)
        {
            string[] names = Enum.GetNames(enumType);
            Array values = Enum.GetValues(enumType);
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(key, Type.GetType("System.String"));
            dataTable.Columns.Add(val, Type.GetType("System.Int32"));
            dataTable.Columns[key].Unique = true;
            for (int i = 0; i < values.Length; i++)
            {
                DataRow dataRow = dataTable.NewRow();
                dataRow[key] = names[i];
                dataRow[val] = (int)values.GetValue(i);
                dataTable.Rows.Add(dataRow);
            }
            return dataTable;
        }
        /// <summary>
        /// 初始化一个dattable
        /// </summary>
        /// <param name="nameList">table的列字段名</param>
        /// <returns></returns>
        public static DataTable CreateTable(IList<string> nameList)
        {
            if (nameList.Count <= 0)
            {
                return null;
            }
            DataTable dataTable = new DataTable();
            foreach (string current in nameList)
            {
                dataTable.Columns.Add(current, typeof(string));
            }
            return dataTable;
        }
        /// <summary>
        /// 传入一个包含列名、列数据类型的字典集合，初始化一个datatable
        /// </summary>
        /// <param name="nameDict">键是table的列名，值是table的类型</param>
        /// <returns></returns>
        public static DataTable CreateTable(IDictionary<string,Type> nameDict)
        {
            if (nameDict.Count <= 0)
            {
                return null;
            }
            DataTable dataTable = new DataTable();
            foreach (KeyValuePair<string,Type> current in nameDict)
            {
                dataTable.Columns.Add(current.Key,current.Value );
            }
            return dataTable;
        }
        
        /// <summary>
        /// 将web表单中post到服务器的键值集合一一对应为实体类对象赋值
        /// 要求：键值列名称必须与实体类名称一致
        /// 实例：
        /// System.Collections.Specialized.NameValueCollection ParamCollection = context.Request.Params;//将webpost的键值对赋值给对象ParamCollection
        /// MyEntity Entity = new MyEntity();//申请一个MyEntity类型的实例Entity
        /// WebForm2Entity<MyEntity>(ref Entity, ParamCollection);//转换后，Entity就成功获取相应值了
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="t">实体类对象</param>
        /// <param name="form">web请求的键值列</param>
        /// <returns></returns>
        public static T WebForm2Entity<T>(System.Collections.Specialized.NameValueCollection form) where T : class
        {
            //反射生成泛型对象类的实体，并初始化
            T t = (default(T) == null) ? Activator.CreateInstance<T>() : default(T);
            //遍历表单键值对
            //获取生成的对象的属性信息
            PropertyInfo[] properties = t.GetType().GetProperties();
            PropertyInfo[] array = properties;

            Dictionary<string, string> namevalueDict = new Dictionary<string, string>(form.Count);
            foreach (string _key in form.Keys)
            {
                namevalueDict.Add(_key, form[_key]);
            }

            //遍历属性，将相应的table值赋值给实体
            for (int i = 0; i < array.Length; i++)
            {
                PropertyInfo propertyInfo = array[i];
                string name = propertyInfo.Name;
                if (namevalueDict.ContainsKey(name) && propertyInfo.CanWrite)
                {
                    object obj = ConvertHelper.ConvertTo(namevalueDict[name], propertyInfo.PropertyType);
                    //如果table中此列的值为null，则将此属性set为null
                    //注意，如果 是一些引用类型，不能将引用值设置为null，就会抛出异常
                    //如 datetime类型，所以建议class中 datetime应该表示为 datetime？或者 Nullable<dateitme>

                    if (obj != null)
                    {
                        propertyInfo.SetValue(t, obj, null);
                    }
                }
            }

            return t;
        }


        private static string _exceptionMessage;
        public string ExceptionMessage
        { 
            get 
            {
                return IListHelper._exceptionMessage;
            } 
            set 
            {
                IListHelper._exceptionMessage = value;
            } 
        }
    }
}
